#include "../CMainServer/CMainServer.h"
#include "ExceptionHandler.h"
#include "../common/glog.h"
#include <DbgHelp.h>
#include <io.h>
#include <direct.h>
#include <Shlwapi.h>
//////////////////////////////////////////////////////////////////////////
const char* g_pszExecuteFunc_WorldThread = NULL;
const char* g_pszExecuteFunc_ServerThread = NULL;
const char* g_pszExecuteFunc_DBThread = NULL;
const char* g_pszExecuteFunc_UIThread = NULL;

int g_nExecuteFunc_WorldThread = 0;
//////////////////////////////////////////////////////////////////////////
LONG WINAPI BM_UnhandledExceptionFilter(_EXCEPTION_POINTERS* pExceptionInfo)
{
#ifdef _DEBUG
	return EXCEPTION_EXECUTE_HANDLER;
#endif
	CMainServer::GetInstance()->SetAppException();

	char szBuf[MAX_PATH];
	GetModuleFileName(NULL, szBuf, MAX_PATH);
	PathRemoveFileSpec(szBuf);
#ifdef _BIN_PATH
	// remove current path
	size_t uStrlen = strlen(szBuf);
	if (0 == uStrlen)
	{
		return EXCEPTION_EXECUTE_HANDLER;
	}
	for (size_t i = uStrlen - 1; i >= 0; --i)
	{
		if (szBuf[i] == '\\' ||
			szBuf[i] == '/')
		{
			// done
			break;
		}
		szBuf[i] = '\0';
	}
#endif
	strcat(szBuf, "\\Dump");

	if(!PathFileExists(szBuf))
	{
		mkdir(szBuf);
	}

	SYSTEMTIME st;
	GetLocalTime(&st);
	char szDumpFileName[50];
	sprintf(szDumpFileName, "\\%02d-%02d-%02d-%02d-%02d.dmp",
		st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute);
	strcat(szBuf, szDumpFileName);

	HANDLE hFile = ::CreateFile(  
		szBuf,   
		GENERIC_WRITE,   
		0,   
		NULL,   
		CREATE_ALWAYS,   
		FILE_ATTRIBUTE_NORMAL,   
		NULL);
	if(hFile != INVALID_HANDLE_VALUE)
	{
		MINIDUMP_EXCEPTION_INFORMATION einfo;
		einfo.ThreadId = GetCurrentThreadId();
		einfo.ExceptionPointers = pExceptionInfo;
		einfo.ClientPointers = FALSE;

		MiniDumpWriteDump(GetCurrentProcess(),
			GetCurrentProcessId(),
			hFile,
			MiniDumpWithFullMemory,
			&einfo,
			NULL,
			NULL);

		CloseHandle(hFile);
	}

	sprintf(szBuf, "Exception!Address:%08X Code:%d",
		(DWORD)pExceptionInfo->ExceptionRecord->ExceptionAddress,
		pExceptionInfo->ExceptionRecord->ExceptionCode);

	//LOG(ERROR) << "Address:" << (DWORD)pExceptionInfo->ExceptionRecord->ExceptionAddress << " CODE:" << pExceptionInfo->ExceptionRecord->ExceptionCode;
	LOG(ERROR) << szBuf;

	/*if(g_pszExecuteFunc_DBThread != NULL)
	{
		LOG(ERROR) << "FUNCTION IN DB THREAD:" << g_pszExecuteFunc_DBThread;
	}
	if(g_pszExecuteFunc_ServerThread != NULL)
	{
		LOG(ERROR) << "FUNCTION IN SERVER THREAD:" << g_pszExecuteFunc_ServerThread;
	}
	if(g_pszExecuteFunc_WorldThread != NULL)
	{
		LOG(ERROR) << "FUNCTION IN WORLD THREAD:" << g_pszExecuteFunc_WorldThread;
	}
	if(g_pszExecuteFunc_UIThread != NULL)
	{
		LOG(ERROR) << "FUNCTION IN UI THREAD:" << g_pszExecuteFunc_UIThread;
	}
	LOG(ERROR) << "FUNCTION LINE WORLD THREAD:" << g_nExecuteFunc_WorldThread;*/
	google::FlushLogFiles(google::GLOG_INFO);

	LOG(ERROR) << "Stack information generated by StackWalker:";
	StackWalkerLog sw;
	sw.ShowCallstack(GetCurrentThread(), pExceptionInfo->ContextRecord);

	MessageBox(NULL, szBuf, "EXCEPTION", MB_ICONERROR | MB_TASKMODAL);

	return EXCEPTION_EXECUTE_HANDLER;
}


//////////////////////////////////////////////////////////////////////////
void StackWalkerLog::OnOutput(LPCSTR szText)
{
	LOG(ERROR) << szText;
	google::FlushLogFiles(google::GLOG_INFO);
}